home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / e33el2.zip / emacs / 19.33 / lisp / ediff.el < prev    next >
Text File  |  1996-07-02  |  44KB  |  1,238 lines

  1. ;;; ediff.el --- a comprehensive visual interface to diff & patch
  2.  
  3. ;; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
  6. ;; Created: February 2, 1994
  7. ;; Keywords: comparing, merging, patching, version control.
  8.  
  9. (defconst ediff-version "2.61" "The current version of Ediff")
  10. (defconst ediff-date "June 10, 1996" "Date of last update")  
  11.  
  12.  
  13. ;; This file is part of GNU Emacs.
  14.  
  15. ;; GNU Emacs is free software; you can redistribute it and/or modify
  16. ;; it under the terms of the GNU General Public License as published by
  17. ;; the Free Software Foundation; either version 2, or (at your option)
  18. ;; any later version.
  19.  
  20. ;; GNU Emacs is distributed in the hope that it will be useful,
  21. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23. ;; GNU General Public License for more details.
  24.  
  25. ;; You should have received a copy of the GNU General Public License
  26. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  27. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  28. ;; Boston, MA 02111-1307, USA.
  29.  
  30. ;;; Commentary:
  31.  
  32. ;; Never read that diff output again!
  33. ;; Apply patch interactively!
  34. ;; Merge with ease!
  35.  
  36. ;; This package provides a convenient way of simultaneous browsing through
  37. ;; the differences between a pair (or a triple) of files or buffers.  The
  38. ;; files being compared, file-A, file-B, and file-C (if applicable) are
  39. ;; shown in separate windows (side by side, one above the another, or in
  40. ;; separate frames), and the differences are highlighted as you step
  41. ;; through them.  You can also copy difference regions from one buffer to
  42. ;; another (and recover old differences if you change your mind).
  43.  
  44. ;; Ediff also supports merging operations on files and buffers, including
  45. ;; merging using ancestor versions. Both comparison and merging operations can
  46. ;; be performed on directories, i.e., by pairwise comparison of files in those
  47. ;; directories.
  48.  
  49. ;; In addition, Ediff can apply a patch to a file and then let you step
  50. ;; though both files, the patched and the original one, simultaneously,
  51. ;; difference-by-difference.  You can even apply a patch right out of a
  52. ;; mail buffer, i.e., patches received by mail don't even have to be saved.
  53. ;; Since Ediff lets you copy differences between buffers, you can, in
  54. ;; effect, apply patches selectively (i.e., you can copy a difference
  55. ;; region from file_orig to file, thereby undoing any particular patch that
  56. ;; you don't like).
  57.  
  58. ;; Ediff is aware of version control, which lets the user compare
  59. ;; files with their older versions. Ediff can also work with remote and
  60. ;; compressed files. Details are given below.
  61.  
  62. ;; Finally, Ediff supports directory-level comparison, merging and patching.
  63. ;; See the on-line manual for details.
  64.  
  65. ;; This package builds upon the ideas borrowed from emerge.el and several
  66. ;; Ediff's functions are adaptations from emerge.el. Much of the functionality
  67. ;; Ediff provides is also influenced by emerge.el.
  68.  
  69. ;; The present version of Ediff supersedes Emerge. It provides a superior user
  70. ;; interface and has numerous major features not found in Emerge. In
  71. ;; particular, it can do patching, and 2-way and 3-way file comparison,
  72. ;; merging, and directory operations.
  73.  
  74.  
  75.  
  76. ;;; Bugs:
  77.  
  78. ;;  1. The undo command doesn't restore deleted regions well. That is, if
  79. ;;  you delete all characters in a difference region and then invoke
  80. ;;  `undo', the reinstated text will most likely be inserted outside of
  81. ;;  what Ediff thinks is the current difference region. (This problem
  82. ;;  doesn't seem to exist with XEmacs.)
  83. ;;
  84. ;;  If at any point you feel that difference regions are no longer correct,
  85. ;;  you can hit '!' to recompute the differences.
  86.  
  87. ;;  2. On a monochrome display, the repertoire of faces with which to
  88. ;;  highlight fine differences is limited. By default, Ediff is using
  89. ;;  underlining. However, if the region is already underlined by some other
  90. ;;  overlays, there is no simple way to temporarily remove that residual
  91. ;;  underlining. This problem occurs when a buffer is highlighted with
  92. ;;  hilit19.el or font-lock.el packages. If this residual highlighting gets
  93. ;;  in the way, you can do the following. Both font-lock.el and hilit19.el
  94. ;;  provide commands for unhighlighting buffers. You can either place these
  95. ;;  commands in `ediff-prepare-buffer-hook' (which will unhighlight every
  96. ;;  buffer used by Ediff) or you can execute them interactively, at any time
  97. ;;  and on any buffer.
  98.  
  99.  
  100. ;;; Acknowledgements:
  101.  
  102. ;; Ediff was inspired by Dale R. Worley's <drw@math.mit.edu> emerge.el.
  103. ;; Ediff would not have been possible without the help and encouragement of
  104. ;; its many users. See Ediff on-line Info for the full list of those who
  105. ;; helped. Improved defaults in Ediff file-name reading commands.
  106.  
  107. ;;; Code:
  108.  
  109. (require 'ediff-init)
  110. ;; ediff-mult is always required, because of the registry stuff
  111. (require 'ediff-mult)
  112.  
  113. (eval-when-compile
  114.   (load "dired")
  115.   (load-file "./ediff-ptch.el")
  116.   (load-file "./ediff-vers.el")
  117.   (load "pcl-cvs" 'noerror))
  118.  
  119. (defvar ediff-use-last-dir nil
  120.   "*If t, Ediff uses previous directory as default when reading file name.")
  121.   
  122. (defvar ediff-last-dir-A nil
  123.   "Last directory used by an Ediff command for file-A.")
  124. (defvar ediff-last-dir-B nil
  125.   "Last directory used by an Ediff command for file-B.")
  126. (defvar ediff-last-dir-C nil
  127.   "Last directory used by an Ediff command for file-C.")
  128. (defvar ediff-last-dir-ancestor nil
  129.   "Last directory used by an Ediff command for the ancestor file.")
  130.  
  131. ;; Some defvars to reduce the number of compiler warnings
  132. (defvar cvs-cookie-handle)
  133. (defvar ediff-last-dir-patch)
  134. (defvar ediff-patch-default-directory)
  135. ;; end of compiler pacifier
  136.  
  137.  
  138. ;; Used as a startup hook to set `_orig' patch file read-only.
  139. (defun ediff-set-read-only-in-buf-A ()
  140.   (ediff-eval-in-buffer ediff-buffer-A
  141.     (toggle-read-only 1)))
  142.  
  143. ;; Return a plausible default for ediff's first file:
  144. ;; In dired, return the file name under the point, unless it is a directory
  145. ;; If the buffer has a file name, return that file name.
  146. (defun ediff-get-default-file-name ()
  147.   (cond ((eq major-mode 'dired-mode)
  148.      (let ((f (dired-get-filename nil 'no-error)))
  149.        (if (and (stringp f) (not (file-directory-p f)))
  150.            f)))
  151.     ((buffer-file-name (current-buffer))
  152.      (file-name-nondirectory (buffer-file-name (current-buffer))))
  153.     ))
  154.  
  155. ;;; Compare files/buffers
  156.  
  157. ;;;###autoload
  158. (defun ediff-files (file-A file-B &optional startup-hooks)
  159.   "Run Ediff on a pair of files, FILE-A and FILE-B."
  160.   (interactive
  161.    (let ((dir-A (if ediff-use-last-dir
  162.             ediff-last-dir-A
  163.           default-directory))
  164.      dir-B f)
  165.      (list (setq f (ediff-read-file-name
  166.             "File A to compare" dir-A 
  167.             (ediff-get-default-file-name)))
  168.        (ediff-read-file-name "File B to compare" 
  169.                  (setq dir-B
  170.                        (if ediff-use-last-dir
  171.                        ediff-last-dir-B 
  172.                      (file-name-directory f)))
  173.                  (progn
  174.                    (setq file-name-history
  175.                      (cons (ediff-abbreviate-file-name
  176.                         (expand-file-name
  177.                          (file-name-nondirectory f)
  178.                          dir-B))
  179.                            file-name-history))
  180.                    f))
  181.        )))
  182.   (ediff-files-internal file-A 
  183.             (if (file-directory-p file-B)
  184.                 (expand-file-name
  185.                  (file-name-nondirectory file-A) file-B)
  186.               file-B)
  187.             nil ; file-C
  188.             startup-hooks
  189.             'ediff-files))
  190.   
  191. ;;;###autoload
  192. (defun ediff-files3 (file-A file-B file-C &optional startup-hooks)
  193.   "Run Ediff on three files, FILE-A, FILE-B, and FILE-C."
  194.   (interactive
  195.    (let ((dir-A (if ediff-use-last-dir
  196.             ediff-last-dir-A
  197.           default-directory))
  198.      dir-B dir-C f ff)
  199.      (list (setq f (ediff-read-file-name
  200.             "File A to compare" dir-A
  201.             (ediff-get-default-file-name)))
  202.        (setq ff (ediff-read-file-name "File B to compare" 
  203.                       (setq dir-B
  204.                         (if ediff-use-last-dir
  205.                             ediff-last-dir-B
  206.                           (file-name-directory f)))
  207.                       (progn
  208.                         (setq file-name-history
  209.                           (cons
  210.                            (ediff-abbreviate-file-name